package Day_0208.Redis;

/**
 * @author zxc
 * @date 2023/02/08 22:55
 **/
public class Redis_SingleThread {
    public static void main(String[] args) {
        /**
         * Redis为啥是单线程的
         * ===》
         * 1.官方FAQ表示，因为Redis是基于内存的操作，CPU不是Redis的瓶颈，Redis的瓶颈最有可能是机器内存大小或者网络带宽。
         * 2.既然单线程容易实现，而且CPU不会成为瓶颈，那就顺理成章地采用单线程的方案了（毕竟采用多线程会有很多麻烦！）
         *
         * 3.Redis利用队列技术，将并发访问变为串行访问
         * 1）绝大部分请求是纯粹的内存操作（非常快速）
         * 2）采用单线程,避免了不必要的上下文切换和竞争条件
         * 3）基于IO多路复用机制;
         *
         * 4.Redis单线程的优点：
         * （1）速度快，因为数据存在内存中，类似于HashMap，HashMap的优势就是查找和操作的时间复杂度都是O(1)
         * （2）支持丰富数据类型，支持string，list，set，sorted set，hash
         * （3）支持事务，操作都是原子性，所谓的原子性就是对数据的更改要么全部执行，要么全部不执行
         * （4）丰富的特性：可用于缓存，消息，按key设置过期时间，过期后将会自动删除
         *
         * 5.如何解决redis的并发竞争key问题
         * 同时有多个子系统去set一个key。这个时候要注意什么呢？
         * 不推荐使用redis的事务机制。因为我们的生产环境，基本都是redis集群环境，做了数据分片操作。
         * 你一个事务中有涉及到多个key操作的时候，这多个key不一定都存储在同一个redis-server上。
         *
         * (1)如果对这个key操作，不要求顺序：
         * ===》 准备一个分布式锁，大家去抢锁，抢到锁就做set操作即可;
         *
         * (2)如果对这个key操作，要求顺序：
         * ===》 分布式锁+时间戳。
         * 假设这会系统B先抢到锁，将key1设置为{valueB 3:05}。
         * 接下来系统A抢到锁，发现自己的valueA的时间戳早于缓存中的时间戳，那就不做set操作了。
         * (3) 利用队列，将set方法变成串行访问也可以redis遇到高并发，
         * 如果保证读写key的一致性 对redis的操作都是具有原子性的,是线程安全的操作,你不用考虑并发问题,redis内部已经帮你处理好并发的问题了。
         *
         */
    }
}
